/**
 * @file gestiondesmessages.c
 * @author Florian Castellane <florian.castellane@grenoble-inp.org>
 * @author Christian Proust <christian.proust@phelma.grenoble-inp.fr>
 * @date Tue Sep 25 23:26:00 2012
 * @brief Fonctions de gestion des messages.
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h> // fonctions à nombre variable d'arguments
#include <time.h>
#include "include/gestiondesmessages.h"
#include "include/gestiondefichier.h"
#define smallcat 0


// Fichier de journalisation
static FICHIER_JOURNAL Fichier_journal = NULL;

extern NIVEAUERREUR NIVEAU_DE_VERBOSITE;

/**
 *
 * @return date d'exécution de la fonction
 * @brief pointeur de structure renvoyant la date
 *
 */

static struct tm* date(void)
{
    time_t date = time(NULL);
    return localtime(&date);
}

/**
 *
 * @brief fonction écrivant le niveau d'erreur dans le journal
 *
 */

static void ecritniveauerreur(NIVEAUERREUR niveau)
{
    if (!Fichier_journal) return;   // ne rien faire si le fichier journal n'est pas ouvert

    /*
    if (niveau == NIVEAU_ERROR)
    {
        printf("");  // sert uniquement à placer un breakpoint pour debugger
    }
    */

    if (niveau <= NIVEAU_ERROR)
    {
        static const char *tab[] =
        {
    /**/    "[DEBOGAGE]",
    /**/    "[INFORMATION]",
    /**/    "[AVERTISSEMENT]",
    /**/    "[ERREUR]"
        };
        fprintf(Fichier_journal,"%s\t",tab[niveau]);

        if (niveau == NIVEAU_ERROR)
        {
            fprintf(stderr, "%s\t",tab[niveau]);
        }
        else printf("%s\t",tab[niveau]);
    }

}

/**
 *
 * @brief fonction écrivant l'heure dans le journal
 *
 */

static void ecritdate(NIVEAUERREUR niveau)
{
    if(!Fichier_journal) return;    // ne rien faire si le fichier journal n'est pas ouvert
    else
    {
        struct tm *t=date();
        fprintf(Fichier_journal,"%02dh%02d:m%02ds : \t", t->tm_hour, t->tm_min, t->tm_sec);

        if (niveau == NIVEAU_ERROR)
        {
            fprintf(stderr, "%02d:%02d:%02d : \t", t->tm_hour, t->tm_min, t->tm_sec);
        }
        else printf("%02d:%02d:%02d : \t", t->tm_hour, t->tm_min, t->tm_sec);
    }
}


void gestiondesmessages_ecritdebutligne(NIVEAUERREUR niveau)
{
    if (!Fichier_journal) return;   // ne rien faire si le fichier journal n'est pas ouvert
    else if (niveau >= NIVEAU_DE_VERBOSITE) // n'afficher que les messages du niveau demandé ou plus important
    {
        ecritniveauerreur(niveau);
        ecritdate(niveau);
    }
}

//(n,__FILE__,  __LINE__, __FUNCTION__, __VA_ARGS__)
void gestiondesmessages_ecriretexte( NIVEAUERREUR niveau, const char* filename, const unsigned int ligne, const char* nomfonction, const char* texte, ... )   // fonctions a nombre d'arguments variable
{
    if ( !Fichier_journal ) return;
    else if ( niveau >= NIVEAU_DE_VERBOSITE )
    {
        va_list liste_variable_arguments;   // initialisation de la liste d'arguments
        va_start(liste_variable_arguments, texte);  // appel de la macro de liste variable d'arguments
        if (niveau == NIVEAU_ERROR)    fprintf(Fichier_journal, "Fich %s, lign %d, fonc %s", filename, ligne, nomfonction);
            vfprintf(Fichier_journal, texte, liste_variable_arguments); // fprintf a nombre d'arguments variable
        va_end(liste_variable_arguments);

        va_start(liste_variable_arguments, texte);
            if (niveau == NIVEAU_ERROR)
            {
                printf("\a");   // faire bipper l'ordinateur : ring the terminal bell
                fprintf(stderr, "Fich %s, lign %d, fonc %s \t", filename, ligne, nomfonction);
                vfprintf(stderr, texte, liste_variable_arguments);
            }
            else vprintf(texte, liste_variable_arguments);
        va_end(liste_variable_arguments);
    }
}


/**
 *
 * @param nomdefichier nom du fichier de journalisation dans lequel écrire
 * @return 0 en cas de succès
 * @brief initialisation de la gestion des messages
 *
 */

int gestiondesmessages_initialisation(const char* nomdefichier)
{
    int retour=0;
    if(nomdefichier)
    {
        Fichier_journal = ouvrir_fichier(nomdefichier, "w+");
    }
    return retour;
}

/**
 *
 * @return le pointeur de flot vers le fichier de journalisation
 * @brief fermeture de la gestion des messages
 *
 */

int gestiondesmessages_fermer(void)
{
    int i=fclose(Fichier_journal);  // si le fichier s'est bien fermé, fclose retourne 0
    if (i) perror("Erreur de fermeture du fichier de journalisation.");
    return i;
}

void ecrire_syntaxe_programme(int argc, char* argv[])
{
    int i=0;
    ecriremessage(NIVEAU_ERROR,"Le programme a ete lance avec %d argument(s) invalide(s):\n", argc);
    for(i=0; i<argc; i++)
    {
        ecriremessage(NIVEAU_INFO, "Argument %d :\t%s\n", i, argv[i]);
    }
    ecriremessage(NIVEAU_INFO, "La syntaxe correcte est :\tassembleurasm [fichier] [-option]\n");
    ecriremessage(NIVEAU_INFO, "Les options valides sont :\t -q pour le mode discret qui n\'affiche qu\'avertissements \
                                et erreurs, et \t-v pour le mode bavard qui affiche les informations de debogage.\n");
    return;
}

void lire_argument_niveau_de_verbosite(int nb_arguments_programme, char* tableau_arguments_programme[])
{
    switch(nb_arguments_programme)
    {
    /**/case 2:
    /**/        NIVEAU_DE_VERBOSITE = NIVEAU_INFO;
    /**/        break;
    /**/case 3:
    /**/    if (!strcasecmp(tableau_arguments_programme[2],"-q"))
    /**/        {
    /**/            NIVEAU_DE_VERBOSITE = NIVEAU_WARNING;
    /**/        }
    /**/    else if (!strcasecmp(tableau_arguments_programme[2],"-v"))
    /**/        {
    /**/            NIVEAU_DE_VERBOSITE = NIVEAU_DEBUG;
    /**/        }
    /**/    else
    /**/        {
    /**/            ecrire_syntaxe_programme(nb_arguments_programme, tableau_arguments_programme);
    /**/            exit(EXIT_FAILURE);
    /**/        }
    /**/    break;
    /**/default:    // inclut le case 1
    /**/    ecrire_syntaxe_programme(nb_arguments_programme, tableau_arguments_programme);
    /**/    exit(EXIT_FAILURE);
    /**/    break;
    }
    return;
}

int quarantedeuxgatos(const int quarantedeux)
{
    unsigned long long int longcat;
	if (42==quarantedeux)
	{
	(quarantedeux==42);
	}
    ecriremessage(NIVEAU_INFO, "\n");
    ecriremessage(NIVEAU_INFO, "\n");
    ecriremessage(NIVEAU_INFO, "       444444444   222222222222222    \n");
    ecriremessage(NIVEAU_INFO, "      4::::::::4  2:::::::::::::::22  \n");
    ecriremessage(NIVEAU_INFO, "     4:::::::::4  2::::::222222:::::2 \n");
    ecriremessage(NIVEAU_INFO, "    4::::44::::4  2222222     2:::::2 \n");
    ecriremessage(NIVEAU_INFO, "   4::::4 4::::4              2:::::2 \n");
    ecriremessage(NIVEAU_INFO, "  4::::4  4::::4              2:::::2 \n");
    ecriremessage(NIVEAU_INFO, " 4::::4   4::::4           2222::::2  \n");
    ecriremessage(NIVEAU_INFO, "4::::444444::::444    22222::::::22   \n");
    ecriremessage(NIVEAU_INFO, "4::::::::::::::::4  22::::::::222     \n");
    ecriremessage(NIVEAU_INFO, "4444444444:::::444 2:::::22222        \n");
    ecriremessage(NIVEAU_INFO, "          4::::4  2:::::2             \n");
    ecriremessage(NIVEAU_INFO, "          4::::4  2:::::2             \n");
    ecriremessage(NIVEAU_INFO, "          4::::4  2:::::2       222222\n");
    ecriremessage(NIVEAU_INFO, "        44::::::442::::::2222222:::::2\n");
    ecriremessage(NIVEAU_INFO, "        4::::::::42::::::::::::::::::2\n");
    ecriremessage(NIVEAU_INFO, "        444444444422222222222222222222\n");
    ecriremessage(NIVEAU_INFO, "\n");
    ecriremessage(NIVEAU_INFO, "\n");
    ecriremessage(NIVEAU_INFO, "\n");
    ecriremessage(NIVEAU_INFO, "\n");
    ecriremessage(NIVEAU_INFO, "        |\\=/|  C E C I   N \' E S T   P A S   U N   G A T O !\n");
    ecriremessage(NIVEAU_INFO, "    _   /6 6\\                                               \n");
    ecriremessage(NIVEAU_INFO, "    )) =\\_Y_/=        ,,,,,      |\\=/|.-\"\"\"-.               \n");
    ecriremessage(NIVEAU_INFO, "   ((   / ^ \\        _|||||_     /6 6\\       \\              \n");
    ecriremessage(NIVEAU_INFO, "    \\\\ /| | |\\      {~*~*~*~}   =\\_Y_/=  (_  ;\\             \n");
    ecriremessage(NIVEAU_INFO, "     \\( | | | )   __{*~*~*~*}__    ^//_/-/__///             \n");
    ecriremessage(NIVEAU_INFO, "       `\"\" \"\"`   `-------------`            ((              \n");
    ecriremessage(NIVEAU_INFO, "                                             `          \n");
    ecriremessage(NIVEAU_INFO, "\n");
    ecriremessage(NIVEAU_INFO, "\n");
    return 42;
}
